package gui;

import java.util.Observable;
import java.util.Observer;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

import conference.Author;
import conference.Conference;
import conference.ProgramChair;
import conference.Review;
import conference.Reviewer;
import conference.User;

/**
 * Controls the flow of the various gui panels.
 * @author Dan Garrison
 * @version Fall 2011
 */
public class GuiController implements Observer{
	private static final QuitControl myQuitControl = 
		new QuitControl();
	private static final SaveControl mySaveControl =
		new SaveControl();
	private static final SwitchUserControl myUserControl = 
		new SwitchUserControl();
	private static final SwitchConferenceControl 
	myConferenceControl = new SwitchConferenceControl();
	private Observable myObservable;
	private JFrame myFrame;
	private Conference myConference;
	private User myUser;
	private JPanel myPanel;
	private String myFrameTitle = "Unimplemented";
	/**
	 * Constructs this controller.
	 */
	public GuiController() {
		myObservable = new ChooseConferencePanel();
		myObservable.addObserver(this);
		myPanel = ((ChooseConferencePanel)myObservable).getPanel();	
		myFrameTitle = ((ChooseConferencePanel)myObservable).getTitle();
		myFrame = new JFrame();
		myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setFrame();
		myFrame.setVisible(Boolean.TRUE);
		myQuitControl.addObserver(this);
		mySaveControl.addObserver(this);
		myUserControl.addObserver(this);
		myConferenceControl.addObserver(this);
	}
	
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void update(Observable observed, Object obj) {
		try {
			State state = (State) obj;
			switch(state) {
			case CHOOSE_CONFERENCE:
				myObservable.deleteObserver(this);
				myConference = ((ChooseConferencePanel) observed).getConference();
				myObservable = new ChooseUserGUI(myConference);
				myPanel = ((ChooseUserGUI) myObservable).getPanel();
				myFrameTitle = ((ChooseUserGUI) myObservable).getTitle();
				break;
			case CHOOSE_USER:
				myObservable.deleteObserver(this);
				myUser = ((ChooseUserGUI) myObservable).getUser();
				myObservable = new ChooseRolePanel(myUser, myConference);
				myPanel = ((ChooseRolePanel) myObservable).getPanel();
				myFrameTitle = ((ChooseRolePanel) myObservable).getTitle();
				break;
			case CHOOSE_ROLE:
				myObservable.deleteObserver(this);
				myUser = ((ChooseRolePanel) myObservable).getUser();
				System.err.println("Choose Role myUser = " + myUser.getClass());
				if (myUser.getClass().equals(Author.class)) {
					myObservable = new AuthorSubmitManuscriptPanel(myConference, (Author)myUser);
					myPanel = ((AuthorSubmitManuscriptPanel) myObservable).getPanel();
					myFrameTitle = ((AuthorSubmitManuscriptPanel) myObservable).getTitle();
				} else if (myUser.getClass().equals(Reviewer.class)) {
					myObservable = new ReviewerSubmitPanel(myConference, (Reviewer)myUser);
					myPanel = ((ReviewerSubmitPanel) myObservable).getPanel();
					myFrameTitle = ((ReviewerSubmitPanel) myObservable).getTitle();
				} else if (myUser.getClass().equals(ProgramChair.class)) {
					myObservable = new ViewManuscriptPanel(myConference);
					myPanel = ((ViewManuscriptPanel) myObservable).getPanel();
					myFrameTitle = ((ViewManuscriptPanel) myObservable).getTitle();
				} else {
					System.err.println("There was a problem " +
							"in the " +
							"Choose role panel.  " +
							"myUser was not author, " +
							"reviewer or pc.");
				}
				break;
			case VIEW_MANUSCRIPT:
				myObservable.deleteObserver(this);
				myObservable = new ManuscriptDecisionPanel(
					((ViewManuscriptPanel) myObservable).
					getViewedManuscript()
				);
				myPanel = ((ManuscriptDecisionPanel)
						myObservable).getPanel();
				myFrameTitle = ((ManuscriptDecisionPanel)
						myObservable).getTitle();
				break;
			case EVAL_MANUSCRIPT:
				System.err.println("Manuscript Decision has been made");
				myObservable.deleteObserver(this);
				myConference.updateManuscript(
					((ManuscriptDecisionPanel) 
							myObservable).getManuscript(),
					((ManuscriptDecisionPanel) 
							myObservable).getStatus()
				);
				myObservable = 
					new ViewManuscriptPanel(myConference);
				myPanel = ((ViewManuscriptPanel) 
						myObservable).getPanel();
				myFrameTitle = ((ViewManuscriptPanel) 
						myObservable).getTitle();
				break;
			case AUTHOR_SUBMITS:
				myObservable.deleteObserver(this);
				myObservable = new AuthorSubmitManuscriptPanel(myConference, (Author)myUser);
				myPanel = ((AuthorSubmitManuscriptPanel) myObservable).getPanel();
				break;
			case REVIEW_SUBMITS:
				myObservable.deleteObserver(this);
				myObservable = new ReviewerSubmitPanel(myConference, (Reviewer)myUser);
				myPanel = ((ReviewerSubmitPanel) myObservable).getPanel();
				break;
			case EXIT_SAVE_MANUSCRIPT:
				System.err.println("Do not use State.EXIT_SAVE_MANUSCRIPT instead use" +
						"State.SAVE");
				break;
			case SWITCH_CONFERENCE:		
				myObservable.deleteObserver(this);
				myObservable = new ChooseConferencePanel();
				myObservable.addObserver(this);
				myPanel = ((ChooseConferencePanel)myObservable).getPanel();
				myFrameTitle = ((ChooseConferencePanel)myObservable).getTitle();
				break;
			case SWITCH_USER:
				myObservable.deleteObserver(this);
				myObservable = new ChooseUserGUI(myConference);
				myPanel = ((ChooseUserGUI) myObservable).getPanel();
				myFrameTitle = ((ChooseUserGUI) myObservable).getTitle();
				break;
			case SAVE:
				System.err.println("Attempting to save conference.");
				ConsumeXMLData.updateConference(myConference, "conferences.xml", true);
			default:
					break;	
			}
		} catch (ClassCastException e) {
			System.err.println("GuiController " + e.getMessage());
		}
		myObservable.addObserver(this);
		setFrame();
	}
	
	/**
	 * Helper method to handle panel swapping in the JFrame.
	 */
	private void setFrame() {
		myFrame.setTitle(myFrameTitle);
		myFrame.getContentPane().removeAll();
		myFrame.getContentPane().add(myPanel);
		myFrame.pack();
	}
	
	/**
	 * @return a JButton that triggers quit events.
	 */
	public static JButton getQuitButton() {
		return myQuitControl.getButton();
	}
	
	/**
	 * @return a JButton that triggers save events.
	 */
	public static JButton getSaveButton() {
		return mySaveControl.getButton();
	}
	
	/**
	 * @return a JButton that triggers user switch event.
	 */
	public static JButton getSwitchUserButton() {
		return myUserControl.getButton();
	}
	
	/**
	 * @return a JButton that fires conference switch event
	 */
	public static JButton getSwitchConferenceButton() {
		return myConferenceControl.getButton();
	}
}